package com.tudouji.project.customer.service.impl;

import com.tudouji.common.exception.CustomException;
import com.tudouji.common.utils.DateUtils;
import com.tudouji.common.utils.IdUtils;
import com.tudouji.common.utils.SecurityUtils;
import com.tudouji.common.utils.StringUtils;
import com.tudouji.framework.security.LoginUser;
import com.tudouji.framework.web.domain.AjaxResult;
import com.tudouji.project.bill.domain.Recharge;
import com.tudouji.project.bill.domain.Sellform;
import com.tudouji.project.bill.domain.Sellitem;
import com.tudouji.project.bill.service.ISellformService;
import com.tudouji.project.customer.domain.Cashflow;
import com.tudouji.project.customer.domain.Customer;
import com.tudouji.project.customer.domain.CustomerBalance;
import com.tudouji.project.customer.domain.Receivableflow;
import com.tudouji.project.customer.mapper.CustomerMapper;
import com.tudouji.project.customer.mapper.ReceivableflowMapper;
import com.tudouji.project.customer.service.ICashflowService;
import com.tudouji.project.customer.service.ICustomerBalanceService;
import com.tudouji.project.customer.service.ICustomerService;
import com.tudouji.project.customer.service.IReceivableflowService;
import com.tudouji.project.pay.domain.SfPrebalanceRecord;
import com.tudouji.project.pay.service.ISfPrebalanceRecordService;
import com.tudouji.project.system.domain.SysUser;
import com.tudouji.project.system.service.impl.SysUserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 账户应收账款流水Service业务层处理
 *
 * @author tudouji
 * @date 2022-05-19
 */
@Service
@Slf4j
public class ReceivableflowServiceImpl implements IReceivableflowService
{
    @Autowired
    private ReceivableflowMapper receivableflowMapper;
    @Autowired
    private ISellformService sellformService;
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private SysUserServiceImpl sysUserService;
    @Autowired
    private ISfPrebalanceRecordService prebalanceRecordService;
    @Autowired
    private ICashflowService cashflowService;

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private ICustomerBalanceService customerBalanceService;
    /**
     * 查询账户应收账款流水
     *
     * @param guid 账户应收账款流水ID
     * @return 账户应收账款流水
     */
    @Override
    public Receivableflow selectReceivableflowById(String guid)
    {
        return receivableflowMapper.selectReceivableflowById(guid);
    }

    /**
     * 查询账户应收账款流水列表
     *
     * @param receivableflow 账户应收账款流水
     * @return 账户应收账款流水
     */
    @Override
    public List<Receivableflow> selectReceivableflowList(Receivableflow receivableflow)
    {
        return receivableflowMapper.selectReceivableflowList(receivableflow);
    }

    /**
     * 新增账户应收账款流水
     *
     * @param receivableflow 账户应收账款流水
     * @return 结果
     */
    @Override
    public int insertReceivableflow(Receivableflow receivableflow)
    {
        return receivableflowMapper.insertReceivableflow(receivableflow);
    }

    /**
     * 修改账户应收账款流水
     *
     * @param receivableflow 账户应收账款流水
     * @return 结果
     */
    @Override
    public int updateReceivableflow(Receivableflow receivableflow)
    {
        return receivableflowMapper.updateReceivableflow(receivableflow);
    }

    /**
     * 批量删除账户应收账款流水
     *
     * @param guids 需要删除的账户应收账款流水ID
     * @return 结果
     */
    @Override
    public int deleteReceivableflowByIds(String[] guids)
    {
        return receivableflowMapper.deleteReceivableflowByIds(guids);
    }

    /**
     * 删除账户应收账款流水信息
     *
     * @param guid 账户应收账款流水ID
     * @return 结果
     */
    @Override
    public int deleteReceivableflowById(String guid)
    {
        return receivableflowMapper.deleteReceivableflowById(guid);
    }

    /**
     * 20231010   应收账款流水表、以及客户层应收账款处理
     * cust        客户信息
     * sellform    销售订单
     * setlAmount  发生额，不传则获取sellform的结算金额
     * type        1 - 正向交易  2 - 反向核销
     * @throws Exception
     */
    @Override
    @Transactional
    public void saveRecableLogs(Customer cust, Sellform sale, BigDecimal setlAmount,
                                Integer type,String linkedTable,Long linkedId,String linkedCode,String remark) {
        Receivableflow low=new Receivableflow();

        low.setCustomerid(cust.getGuid());
        low.setCode(linkedCode);
        if(setlAmount==null){
            setlAmount = sale.getFinalamount();
        }

        low.setLinkid(linkedId);
        low.setLinkedTable(linkedTable);
        if(type==2 && linkedId!=-1l){
            //反向核销应收账款余额，检查到正向交易后可以执行，否则不执行
            //linkedId==-1 表示对初始化应收账款余额的核销，不需要检查正向交易
            Receivableflow lookup = new Receivableflow();
            lookup.setLinkedTable(linkedTable);
            lookup.setLinkid(linkedId);
            lookup.setAmount(setlAmount);
            List<Receivableflow> list = receivableflowMapper.selectReceivableflowList(lookup);
            if(list.size()==0){
                throw new CustomException("核销客户应收账款失败！");
            }
        }
        if(type==2){
            setlAmount = setlAmount.negate();
        }
        low.setAmount(setlAmount);

        if(cust.getRecbalance()==null){
            cust.setRecbalance(setlAmount);
        }else{
            cust.setRecbalance(cust.getRecbalance().add(setlAmount));
        }

        low.setRecbalance(cust.getRecbalance());
        SysUser user=null;
        if(SecurityUtils.getAuthentication() != null && SecurityUtils.getAuthentication().getPrincipal() instanceof LoginUser){
            user=SecurityUtils.getLoginUser().getUser();
        }else{
            //获取销售订单的下单用户
            user=sysUserService.selectUserById(sale.getCreateBy());
        }

        if (null != user){
            low.setOperatorid(user.getGuid());
            low.setOperator(user.getNickName());
        }
        low.setType(type);//1-正向交易 2 - 反向交易
        low.setGuid(IdUtils.fastSimpleUUID());
        low.setRemark(remark);
        receivableflowMapper.insertReceivableflow(low);

        //更新应收余额
        /*Customer customer=new Customer();
        customer.setGuid(cust.getGuid());
        customer.setRecbalance((cust.getRecbalance()==null?BigDecimal.ZERO:cust.getRecbalance()).add(setlAmount));
        customerMapper.updateCustomer(customer);*/
    }

    /**
     * 数据初始化
     * 1、	新增初始化批量程序，遍历所有未核销、已出库的、非全款预付的销售订单。
     * 2、	以结算金额生成该订单的应收账款明细数据、并累加应收账款余额。
     */
    @Transactional
    @Override
    public AjaxResult dataInit() {

        if(1==1){
            //20231016 数据初始化方案调整，只做抹零，其他不做了
            //20231117 已经完成所有初始化
            return AjaxResult.success();
        }

        //20231013 首先处理预收款余额为负数的数据
        process4Prebalance();

        Sellform sellform = new Sellform();
        sellform.setPaytypes(new Integer[]{2,3});
        sellform.setMinstatusL("55");
        sellform.setMoneybackStatusNo(3);
        List<Sellform> sellformList = sellformService.selectSellformList(sellform);

        for (int i = 0; i < sellformList.size(); i++) {
            Sellform sf = sellformList.get(i);
            //20231016 不处理电商订单
            if(sf.getFlag()==4){
                continue;
            }
            Customer cust = customerMapper.selectCustomerById(sf.getCustomerguid());
            this.saveRecableLogs(cust, sf,sf.getFinalamount(),1,"sellform", sf.getId(), sf.getSellcode(),"数据初始化");
            customerMapper.updateCustomer(cust);
        }

        return AjaxResult.success();
    }

    private void process4Prebalance() {
        System.out.println("===data init process4Prebalance start===");
        Customer lookfor=new Customer();
//        lookfor.setFlagPrebalance(1);
        int initCount=0,recBalanceCount=0,minusCount=0;
        boolean customerChanged=false;
        List<Customer> Customerlist = customerMapper.selectCustomerList(lookfor);
        for(Customer customer:Customerlist){
            //预收款余额初始化为0并登记初始化记录
            //20231117 不用INIT进行初始化了，修改为nocurrencyBalance
            if(customer.getNocurrprebalance()!=null
                && initPreBalance(customer,customer.getNocurrprebalance())){
                customer.setNocurrprebalance(null);
                customerChanged=true;
                initCount++;
            }

            if(customer.getRecbalanceManual()!=null && customer.getRecbalanceManual().compareTo(BigDecimal.ZERO)>0){
                //有初始化应收账款余额，需要处理

                if(processRecbalance(customer)) {
                    recBalanceCount++;
                    customerChanged=true;
                }
            }

            if(customer.getPrebalance()!=null && customer.getPrebalance().signum()==-1){
                //客户预收款余额为负，初始化为0
                initPreBalance(customer,BigDecimal.ZERO);
                minusCount++;
            }

            //初始化当前客户的每日余额
            //processCustomerBalance(customer);

            if(customerChanged) customerService.updateCustomer(customer);
            customerChanged=false;
        }
        System.out.println("===process4Prebalance initCount+"+initCount);
        System.out.println("===process4Prebalance recBalanceCount+"+recBalanceCount);
        System.out.println("===process4Prebalance minusCount+"+minusCount);
    }

    //初始化当前客户的每日余额表
    private void processCustomerBalance(Customer customer) {
        String dateString = "2023-10-29 23:59:59";
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date fromDate=null,toDate=new Date();
        try{
            fromDate = format.parse(dateString);
        }catch (Exception e){

        }
        log.info("process for customer:"+customer.getName());
        while (fromDate.compareTo(toDate)<=0){
            //查找当前客户的小于等于fromDate的预收款余额流水记录
            Cashflow cashflow = new Cashflow();
            cashflow.setCustomerid(customer.getGuid());
            cashflow.setMinCreatetime(fromDate);
            List<Cashflow> cashflows = cashflowService.selectCashflowList(cashflow);
            //查询当日应收账款流水，获取当日应收账款余额
            Receivableflow receivableflow = new Receivableflow();
            receivableflow.setCustomerid(customer.getGuid());
            receivableflow.setMinCreatetime(fromDate);
            List<Receivableflow> receivableflows = receivableflowMapper.selectReceivableflowList(receivableflow);
            BigDecimal recBalance = BigDecimal.ZERO;
            BigDecimal preBalance = BigDecimal.ZERO;
            boolean hasRecord=false;
            if(receivableflows.size()>0){
                recBalance = receivableflows.get(0).getRecbalance();
                hasRecord=true;
            }
            if(cashflows.size()>0) {
                preBalance = cashflows.get(0).getPrebalance();
                hasRecord=true;
            }
            if(hasRecord){
                CustomerBalance customerBalance = new CustomerBalance();
                customerBalance.setCustomerGuid(customer.getGuid());
                customerBalance.setPrebalance(preBalance);
                customerBalance.setName(customer.getName());
                customerBalance.setKingdeenum(customer.getKingdeenum());
                customerBalance.setBusinessDate(fromDate);
                customerBalance.setCreateBy("1");
                customerBalance.setRemark("Init");
                customerBalance.setCreateTime(toDate);
                customerBalance.setRecbalance(recBalance);
                customerBalanceService.insertCustomerBalance(customerBalance);
            }

            fromDate = DateUtils.addDay(fromDate,1);
            log.info("fromDate:"+fromDate);
        }
        log.info("End process for customer:"+customer.getName());
    }


    /**
     * 初始化客户的应收账款余额，累加到应收款余额上
     * @param customer
     */
    private boolean processRecbalance(Customer customer) {
        BigDecimal amount = customer.getRecbalanceManual();

        if(amount==null || amount.compareTo(BigDecimal.ZERO)==0){
            return false;
        }
        //伪装一个sellform，调用saveRecableLogs
        Sellform sellform=new Sellform();
        sellform.setFinalamount(amount);
        sellform.setCreateBy(1l);
        saveRecableLogs(customer,sellform,amount,1,"notable",-1l,"Init","系统初始化");
        return true;
    }


    /***
     * 初始化客户层预收款余额为0
     * 财务给的是2023/10/31号的数据，所以，查找到该客户10月31号的余额，调差
     * @param customer
     */
    @Transactional
    public boolean initPreBalance(Customer customer,BigDecimal newBalance) {

        //查找10月31号的余额
        CustomerBalance lookupCusBal = new CustomerBalance();
        lookupCusBal.setCustomerGuid(customer.getGuid());
        Date busDate = DateUtils.parseDate("2023-10-31");
        lookupCusBal.setBusinessDate(busDate);
        List<CustomerBalance> customerBalanceList = customerBalanceService.selectCustomerBalanceList(lookupCusBal);
        BigDecimal initBalance = BigDecimal.ZERO;
        if(customerBalanceList.size()>0){
            initBalance = customerBalanceList.get(0).getPrebalance();
        }

        BigDecimal amount = newBalance.subtract(initBalance);

        if(amount.compareTo(BigDecimal.ZERO)==0){
            return false;
        }
        SysUser user = sysUserService.selectUserById(1l);
        //伪装一个recharge
        Recharge recharge = new Recharge();
        recharge.setCode("Init");
        recharge.setAmount(amount);
        recharge.setRemark("以10月31日余额调差");
        recharge.setType(1);
        customerService.recharge(customer,amount,user,recharge,1,"以10月31日余额调差");
        return true;
    }

    private void minusPreBalance(Customer customer) {
        //查询该客户的所有核销记录列表，已核销的、货到付款或上车付款的订单
        List<SfPrebalanceRecord> records = prebalanceRecordService.hdfkHeXiaoRecordForByCustGuid(customer.getGuid());
        for(SfPrebalanceRecord sfr:records){
            if(customer.getPrebalance()==null || customer.getPrebalance().compareTo(BigDecimal.ZERO)>=0){
                //客户层预收款余额大于等于0，停止
                break;
            }
            Sellform sellform = sellformService.selectSellformById(sfr.getSellformId());
            //不处理电商订单,而且，当前电商订单不生成核销记录，所以理论上销售订单不会是电商订单
            if(sellform.getFlag()==4){
                continue;
            }


            BigDecimal amount = sfr.getAmount();
            //不需要处理客户层应收账款，后续批量程序会根据销售订单的回款状态统一处理
//            customer.setRecbalance(customer.getRecbalance()==null?amount:customer.getRecbalance().add(amount));

            //当前核销记录状态修改为未核销
            sfr.setStatus(1);
            //销售订单状态修改为未核销
//            Sellform sellform = new Sellform();
//            sellform.setId(sfr.getSellformId());
            sellform.setMoneybackStatus(1);

            //累加到预收款余额上，并，生成流水记录
            SysUser user = sysUserService.selectUserById(1l);
            customerService.recharge(customer,amount,user,null,1,"初始化冲回余额不足的销售订单");
//            customer.setPrebalance(customer.getPrebalance().add(amount));
//            customer.setCurrprebalance(customer.getPrebalance().add(amount));
//            Cashflow cashflow= new Cashflow();
//            cashflow.setLinkedTable("sf_prebalance_record");
//            cashflow.setLinkid(sfr.getId().toString());
//            List<Cashflow> cashflows = cashflowService.selectCashflowList(cashflow);
//            if(cashflows.size()==1){
//                Cashflow toBeDel = cashflows.get(0);
//                cashflowService.deleteCashflowById(toBeDel.getGuid());
//            }else{
//                throw new CustomException("found more than 1 cashflows:"+cashflow.getLinkedTable() + ":" + cashflow.getLinkid());
//            }

            sellformService.updateSellform(sellform);
            prebalanceRecordService.updateSfPrebalanceRecord(sfr);
        }
        customerMapper.updateCustomer(customer);

    }

}
